from openpyxl import load_workbook

def _row2dict(row, toprow):
    d = {}
    for i in range(0, len(row)):
        if toprow[i].value in d:
            raise Exception(f"有重名的表头,请检查确认: {toprow[i].value}")
        d[toprow[i].value] = row[i].value
    return d

def isempty(s):
    if s is None: return True
    if str(s).strip() == "": return True
    return False

def loads(file, cls, mapping):
    wb = load_workbook(filename=file)
    sh = wb.worksheets[0]
    toprow = None
    result = []
    for row in sh.rows:
        if row[0].row == 1:
            toprow = row
            continue
        data = _row2dict(row, toprow)
        item = cls()
        for k, c in mapping.items():
            excel_column_name = c["title"]
            required = c.get("required", False)
            default = c.get("default", None)
            v = data.get(excel_column_name, None)
            if required and isempty(v):
                print(row[0].value)
                raise Exception(f"行{row[0].row}字段{excel_column_name}缺失")
            if default is not None and v is None:
                v = default
            setattr(item, k, v)
        result.append(item)
    return result

def loads2dict(file):
    wb = load_workbook(filename=file)
    sh = wb.worksheets[0]
    toprow = None
    result = []
    for row in sh.rows:
        if row[0].row == 1:
            toprow = row
            continue
        data = _row2dict(row, toprow)
        result.append(data)
    return result

if __name__ == '__main__':
    class Test(object):
        a: str
        b: str
    l = loads("1.xlsx", Test, {
        "a": {"title": "A", "required": True},  "b": {"title": "B", "required": True}
    })
    for i in l:
        print(i.a, i.b)